package com.gjy.spring.s4;

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-12-19 10:23:35
 */
// AutowiredAnnotationBeanPostProcessor
public class DigInAutowired {

    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.registerSingleton("bean2", new Bean2()); // 创建过程，依赖注入，初始化 都不会走了
        factory.registerSingleton("bean3", new Bean3());
        factory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
        factory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // 解析 ${}

        // 1. 查找那些属性、方法加了@Autowired，称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        Bean1 bean1 = new Bean1();
//        System.out.println("bean1 = " + bean1);
//        processor.postProcessProperties(null, bean1, "bean1");  // 完成对注解的解析
//        System.out.println("bean1 = " + bean1);
        Method method = AutowiredAnnotationBeanPostProcessor.class
                .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        method.setAccessible(true);
        // 获取Bean1上加了@Value，@Autowired的成员变量，方法参数信息
        InjectionMetadata data = (InjectionMetadata) method.invoke(processor, "bean1", Bean1.class, null);
        System.out.println(data);

        // 2. 调用 InjectionMetadata 进行依赖注入，注入时按类型查找值
        data.inject(bean1, "bean1", null);
        // 3. 如何按类型查找值
        Field field = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor descriptor = new DependencyDescriptor(field, false);
        Object o = factory.doResolveDependency(descriptor, null, null, null); // 获取到Bean3
        System.out.println(o); // 反射调用，将o设置给bean1

        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor d2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);
        Object o1 = factory.doResolveDependency(d2, null, null, null);
        System.out.println("o1 = " + o1);

        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor d3 = new DependencyDescriptor(new MethodParameter(setHome, 0), false);
        Object o2 = factory.doResolveDependency(d3, null, null, null);
        System.out.println("o2 = " + o2);
    }
}
